#include "i2c_bus.h"

#define DBGBUG_TAG "i2c bus"
#include "debug.h"

mt_ssize_t mt_i2c_bus_transfer(mt_i2c_bus_t *i2c_bus, mt_i2c_msg_t msgs[], mt_size_t num)
{
    mt_ssize_t ret;
    
    MT_ASSERT(i2c_bus == MT_NULL);
    MT_ASSERT(i2c_bus->parent.magic != I2C_M_MAGIC);
    MT_ASSERT(msgs == MT_NULL);
    
    if(i2c_bus->ops->xfer == MT_NULL)
        return MT_ENOSYS;
    
    ret = mt_sem_take(&i2c_bus->lock, MT_WAITING_FOREVER);
    if(ret == MT_EOK)
    {
        ret = i2c_bus->ops->xfer(i2c_bus, msgs, num);
        mt_sem_release(&i2c_bus->lock);
    }
    return ret;
}

static mt_err_t mt_i2c_bus_ioctl(struct mt_device *device, mt_uint32_t cmd, void *arg)
{
    mt_ssize_t ret;
    mt_i2c_rdwr_data_t *data;
    mt_i2c_bus_t *i2c_bus = mt_container_of(device, mt_i2c_bus_t, parent);
    
    if(cmd == I2C_M_RDWR)
    {
        MT_ASSERT(arg == MT_NULL);
        
        if(i2c_bus->ops->xfer == MT_NULL)
            return MT_ENOSYS;
        
        data = arg;
        ret = i2c_bus->ops->xfer(i2c_bus, data->msgs, data->num);
        if(ret == data->num)
            return MT_EOK;
        else
            return ret;
    }
    
    return MT_ENOSYS;
}

static mt_device_ops_t i2c_ops =
{
    .ioctl = mt_i2c_bus_ioctl,
};

mt_err_t mt_i2c_bus_register(mt_i2c_bus_t *i2c_bus, const char *name)
{
    mt_err_t result;
    
    MT_ASSERT(i2c_bus == MT_NULL);
    MT_ASSERT(name == MT_NULL);
    MT_ASSERT(i2c_bus->ops == MT_NULL);
    
    mt_sem_init(&i2c_bus->lock, name, 1, 1, MT_IPC_FLAG_FIFO);
    
    i2c_bus->parent.flags = MT_DEVICE_RDWR;
    i2c_bus->parent.magic = I2C_M_MAGIC;
    i2c_bus->parent.ops = &i2c_ops;
    result = mt_device_register(&i2c_bus->parent, name);
    if(result != MT_EOK)
        LOG_E("register i2c bus faied\r\n");

    return result;
}

mt_err_t mt_i2c_client_register(mt_i2c_client_t *i2c_client, const char *client_name, const char *bus_name)
{
    mt_err_t result;
    mt_device_t *tmp;
    
    MT_ASSERT(i2c_client == MT_NULL);
    MT_ASSERT(client_name == MT_NULL);
    MT_ASSERT(bus_name == MT_NULL);
    
    tmp = mt_device_find(bus_name);
    if(tmp == MT_NULL)
    {
        LOG_E("find i2c bus faied\r\n");
        return MT_EEMPTY;
    }
    i2c_client->bus = mt_container_of(tmp, mt_i2c_bus_t, parent);
    
    result = mt_device_register(&i2c_client->parent, client_name);
    if(result != MT_EOK)
        LOG_E("register i2c client faied\r\n");

    return result;
}
